package com.rabbitmq.msgdirection.alternateexchange;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ReturnListener;
import com.rabbitmq.util.ConnectionUtils;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeoutException;

import static com.rabbitmq.common.Constant.NUM3;

/**
 * 备用交换器
 */
@Slf4j
public class AlternateExchange {
    public static void main( String[] args ) {
        try {
            // 创建连接
            Connection connection = ConnectionUtils.getConnection();
            // 创建信道
            Channel channel = connection.createChannel();
            // 备份路由器放到Map
            Map<String, Object> arg = new HashMap<String, Object>(NUM3);
            arg.put("alternate-exchange", "myAe");

            // 创建正常交换器，最后一个参数会指定备份路由器
            channel.exchangeDeclare("normalExchange", "direct",
                    true, false, false, arg);
            // 创建备份交换器
            channel.exchangeDeclare("myAe", "fanout",
                    true, false, false, null);
            // 声明正常交换器绑定的的队列
            channel.queueDeclare("normalQueue", true, false, false, null);
            // 正常队列的绑定
            channel.queueBind("normalQueue", "normalExchange", "normalKey");
            // 声明备份交换器绑定的队列
            channel.queueDeclare("unroutingQueue", true, false, false, null);
            // 备份交换器队列的绑定
            channel.queueBind("unroutingQueue", "myAe", "");
            // 定义要发送的消息
            String message1 = "normal route";
            String message2 = "not normal route";
            // 能正常路由的消息的发送
            channel.basicPublish("normalExchange", "normalKey",
                    null, message1.getBytes());
            // 不能正常路由消息的发送
            channel.basicPublish("normalExchange", "notnormalKey",
                    null, message2.getBytes());
            // 观察消息是否会回退到生产者
            channel.addReturnListener(new ReturnListener() {
                /**
                 * broker(代理服务器)发出basic.return方法之后，就会回调handleReturn方法，
                 * 在这个方法里面我们就可以进行消息的重新发布操作
                 * @param replyCode 312
                 * @param replyText NO_ROUTE：表示消息并没有路由到合适的队列中
                 * @param exchange 交换器
                 * @param routingKey 路由键
                 * @param properties 相关属性
                 * @param body 消息体
                 * @throws IOException
                 */
                @Override
                public void handleReturn( int replyCode, String replyText, String exchange, String routingKey,
                                          AMQP.BasicProperties properties, byte[] body ) throws IOException {
                    String message = new String(body);
                    log.info("replyCode:  " + replyCode);
                    log.info("replyText:  " + replyText);
                    log.info("Basic.Return返回的结果:  " + message);
                }
            });


            ConnectionUtils.close(channel, connection);
        } catch (IOException e) {
            log.info("catch IOException");
        } catch (TimeoutException e) {
            log.info("catch TimeoutException");
        }
    }
}
